﻿#ifndef AUDIOCONTROLER_H    //防止头文件重复包含的标准宏，确保该头文件在编译过程中只被包含一次
#define AUDIOCONTROLER_H
#include "Aconfig.h" //包含项目配置文件，引入之前定义的音频设备路径、模型路径等配置常量

#include <QObject>//Qt核心类，提供信号槽机制和对象管理
#include <QDebug>//Qt调试输出类，用于打印调试信息
#include <QFile>//Qt文件操作类,用于读写文件
#include <QTimer>//定时器类，用于定时触发事件
#include <queue> //C++标准队列库容器，用于存储元素队列


//作用：包含qt音频处理相关类
#include <QAudioFormat>//Qt音频格式设置,定义音频采样率,位深度等参数
#include <QAudioInput>//Qt音频输入类，用于从麦克风捕获音频
#include <QAudioOutput>//Qt音频输出类，用于播放音频到杨声器
#include <QMediaPlayer>//Qt媒体播放类，用于播放音频文件
#include "../resources/snowboy_resources/include/snowboy-detect.h"//包含Snowboy唤醒词检测库，用于实现语音唤醒功能


//Sherpa-ncnn语音识别库
#include "../resources/sherpaNcnn_resources/include/c-api.h"//Sherpa-ncnn的C接口头文件
#include <iostream>//标准I/O
#include <vector> //C++标准向量容器
#include <string>//C++标准字符串类
#include <unordered_map>//C++标准哈希表容器
#include <algorithm>//C++标准算法库
#include <fstream>//C++文件流操作


//sherpa-Onnx语音合成库
#include "../resources/sherpaOnnx_resources/include/c-api.h"//Sherpa-Onnx的C接口头文件
#include <QDir>    //Qt目录操作类，用于路径处理


using namespace std;



#include <QThread>//Qt线程类，支持多线程操作


struct SpeechTask {
    QString content;  // 要播放的语音内容文本
    int priority;     // 任务的优先级数值

    bool operator<(const SpeechTask& other) const {
        return priority < other.priority; // 优先级较高的排在前面
    }
};


//音频控制类定义
class AudioControler : public QObject
{
    Q_OBJECT//Qt宏，启用信号槽机制和元对象系统
public:
    //构造函数
    explicit AudioControler(QObject *parent = 0); //显示构造函数，防止隐式转换
    bool audioInit(); //音频设备初始化函数
    bool snowboyInit();//Snowboy唤醒次检测初始化函数

    bool getAudioControlerInit_state();//获取音频控制器初始化状态

    bool playAudio(QString& audioPath);//播放指定路径的音频文件

    bool sherpancnnInit();//Sherpa-ncnn语音识别初始化函数

    void start_snowboyInterrupt();//启动Snowboy中断检测
    void stop_snowboyInterrupt();//停止Snowboy中断检测

    void sherpaNcnnRecognition(); //执行语音识别
    bool readCommandsFromFile();//从文件读取命令列表
    double calculateSimilarity(const string& userCommand, const string& command);//计算用户命令与预命令的相似度
    string matchCommand(const string& userCommand);//匹配最相似命令
    void processCommand(const string& command_matched);//处理匹配到的命令

    bool sherpaonnxInit();//Sherpa-Onnx语音合成函数

    void generateAudio(const QString &text, const QString &outputFile);//生成语音文件


signals:
    //初始化完成信号
    void initialized_sig();//当音频系统初始化完成后发射此信号

public slots:

    //总初始化入口
    bool initialize();//调用各子系统的初始化函数

    //Snowboy中断处理槽函数
    void snowboyInterrupt();//当检测到唤醒词时触发

    void getSpeechTeskFromController_slot(QString str,int priority);//接受语音任务请求

    void startNextSpeech_slot(); // 播放下一个语音任务


private:
    bool initialized_state = false;

private:
    bool audioDeviceBusy = false;//记录初始化状态和音频设备占用状态

private:
    //Qt音频相关成员
    QAudioInput* audioInput; //音频输入对象指针（录音）
    QAudioOutput* audioOutput; //音频输出对象指针（播放）
    QMediaPlayer* mediaPlayer; //媒体播放器对象指针
    QIODevice* audioDevice; //音频设备I/O 对象指针


    //Snowboy相关成员
    snowboy::SnowboyDetect*snowboyDetect;  //Snowboy唤醒词检测引擎指针

    QByteArray audioBuffer;  //音频数据缓冲区

    //Sherpa-ncnn语音识别相关成员
    SherpaNcnnRecognizer* recognizer; //语音识别器对象指针
    SherpaNcnnStream* stream; //语音流处理对象指针
    vector<string> commands; //存储可识别命令的容器

    //Sherpa-Onnx语音合成相关成员
    SherpaOnnxOfflineTts *tts; //离线文本转语音引擎指针


private:
    //语音任务队列管理
    std::priority_queue<SpeechTask> speechQueue; // 语音任务的优先级队列
    QTimer startNextSpeechTimer; // 定时器控制任务播放
};

#endif // AUDIOCONTROLER_H //头文件保护宏结束
